/*
 * Copyright (c) 2019. Mikes. All rights reserved.
 *
 * You can contact me with sending email to bWlrZXNfMjAxMkAxNjMuY29t for more information!
 */

package com.climber.android.commonsdk.api.interceptor

import androidx.annotation.NonNull
import com.climber.android.commonsdk.api.APITokenType
import com.climber.android.commonsdk.api.entity.AccessHeader
import okhttp3.HttpUrl
import okhttp3.Interceptor
import okhttp3.Request
import okhttp3.Response
import java.io.IOException
import java.io.UnsupportedEncodingException
import java.net.URLEncoder

/**
 * author : Mikes
 * date : 2019/2/25 16:15
 * description :
 */
class AuthorizationInterceptor(private val preferredTokenType: APITokenType = APITokenType.loginTokenPreferred) : Interceptor {
    @Throws(IOException::class)
    override fun intercept(chain: Interceptor.Chain): Response {
        val originalRequest = chain.request()

        val apiTokenType: APITokenType = if (originalRequest.header("tokenType") != null && originalRequest.header("tokenType")?.isNotEmpty() == true) {
            APITokenType.getAPITokenType(originalRequest.header("tokenType") ?: "")
        } else {
            preferredTokenType
        }

        val accessHeader = APITokenType.headers(apiTokenType)
        val originalResponse = chain.proceed(generateNewRequest(originalRequest, originalRequest.url(), accessHeader))

        if (originalResponse.code() in CODE_REDIRECT_START..CODE_REDIRECT_END) {
            val redirectUrl = originalResponse.header("Location")
            if(redirectUrl != null){
                originalResponse.body()?.close()

                return chain.proceed(generateNewRequest(originalRequest, HttpUrl.parse(redirectUrl), accessHeader))
            } else{
                //don't do redirect.
            }
        }

        return originalResponse
    }

    companion object {
        private const val CODE_REDIRECT_START = 300
        private const val CODE_REDIRECT_END = 307

        fun generateNewRequest(originalRequest: Request, appendLangUrl: HttpUrl?, @NonNull accessHeader: AccessHeader): Request {
            val requestBuilder = originalRequest.newBuilder()
                .url(appendLangUrl)
                .header("Accept", accessHeader.accept)
                .header("X-Client-Name", accessHeader.xClientName)
                .header("X-Client-Version", accessHeader.xClientVersion)

            if (accessHeader.authorization.isNotEmpty()) {
                requestBuilder.header("token", accessHeader.authorization)
            }

            return requestBuilder.build()
        }

        //Okhttp header不允许传\n null 中文等特殊字符，此方法使用okhttp的校验方式。
        //校验不通过 返回encode后的字符串
        fun getValueEncoded(value: String?): String {
            if (value == null) return "null"
            val newValue = value.replace("\n", "")
            var i = 0
            val length = newValue.length
            while (i < length) {
                val c = newValue[i]
                if (c <= '\u001f' || c >= '\u007f') {
                    try {
                        return URLEncoder.encode(newValue, "UTF-8")
                    } catch (e: UnsupportedEncodingException) {
                        e.printStackTrace()
                    }

                }
                i++
            }
            return newValue
        }
    }
}
